/**
 * Created by qiushaohua on 14-3-18.
 */
define(['app', 'angular'], function (app, angular) {

    var deps = ['$transition', '$timeout', '$document', '$compile', '$$stackedMap'];

    function hatchStackService ($transition, $timeout, $document, $compile, $$stackedMap) {

        var openedHatch = $$stackedMap.createNew(),
            hatchStack = {},
            hatchWrapper;

        function removeHatch (hatchInstance) {

            var hatch = openedHatch.get(hatchInstance).value;

            //clean up the stack
            openedHatch.remove(hatchInstance);

            //remove window DOM element
            removeAfterAnimate(hatch.domEl, hatch.scope, 300, function () {
                hatch.scope.$destroy();
            });
        }

        function removeAfterAnimate (domEl, scope, emulateTime, done) {
            // Closing animation
            scope.animate = false;

            var transitionEndEventName = $transition.transitionEndEventName;
            if (transitionEndEventName) {
                // transition out
                var timeout = $timeout(afterAnimating, emulateTime);

                domEl.bind(transitionEndEventName, function () {
                    $timeout.cancel(timeout);
                    afterAnimating();
                    scope.$apply();
                });
            } else {
                // Ensure this call is async
                $timeout(afterAnimating, 0);
            }

            function afterAnimating () {
                if (afterAnimating.done) {
                    return;
                }
                afterAnimating.done = true;

                domEl.remove();
                if (done) {
                    done();
                }
            }
        }

        function getHatchContainer () {
            if (hatchWrapper) {
                return hatchWrapper;
            }
            hatchWrapper = angular.element('<div class="wrapper"></div>');
            var container = angular.element('<div class="hatch-container"></div>');
            container.append(hatchWrapper);
            $document.find('body').append(container);
            return hatchWrapper;
        }

        hatchStack.open = function (hatchInstance, hatch) {

            openedHatch.add(hatchInstance, {
                deferred: hatch.deferred,
                scope: hatch.scope
            });

            var angularDomEl = angular.element('<div class="hatch"></div>');
            angularDomEl.addClass(hatch.hatchClass);
            angularDomEl.attr('index', openedHatch.length() - 1);
            angularDomEl.attr('animate', 'animate');
            angularDomEl.html(hatch.content);

            var domEl = $compile(angularDomEl)(hatch.scope);
            openedHatch.top().value.domEl = domEl;

            getHatchContainer().append(domEl);
        };

        hatchStack.close = function (hatchInstance, result) {
            var entity = openedHatch.get(hatchInstance);
            if (entity && entity.value) {
                entity.value.deferred.resolve(result);
                removeHatch(hatchInstance);
            }
        };

        hatchStack.getTop = function () {
            return openedHatch.top();
        };

        return hatchStack;
    }

    hatchStackService.$inject = deps;
    return app.lazy.service('HatchStack', hatchStackService);
});